import re
import xml.dom.minidom
import logging

def getDefault(x, default):
    return ( x if x else default )

def getAdditionalField(i):
    r = {}
    r['name'] = i.getAttribute('name')
    r['title'] = getDefault(i.getAttribute('title'),r['name'])
    r['type'] = getDefault(i.getAttribute('type'),"char")
    r['format'] = i.getAttribute('format')
    return r

def getField(i):
    r = {}
    r['name'] = i.getAttribute('name')
    r['title'] = getDefault(i.getAttribute('title'),r['name'])
    r['begin'] = int(i.getAttribute('begin'),0)
    r['end'] = int(i.getAttribute('end'),0) if i.hasAttribute('end') else None
    r['type'] =  i.getAttribute('type')
    r['format'] = i.getAttribute('format')
    return r

class FieldConfig:
    def __init__(self):
        """
        DataType: ["PacketInfo","Undefined"]
        CommonField: ["hop","nodeid"]
        TypeField["PacketInfo"] = [{fieldname:"value","format":int, "type":uint32, "title": },{fieldname:"value2","format":int, "type":uint32, "title": }]
        """
        self.additionalField = []
        self.commonField = []
        self.commonFieldOnly = []
        self.dataType = []
        self.typedField = {}
        self.typedFieldOnly = {}
        self.conditionByType = {}

def ParsePacketXML(xmlConfigFile):
##    print "xmlConfigFile is ", xmlConfigFile
    fc = FieldConfig()
    file = open(xmlConfigFile)
    content = file.readline()        
    m = re.search("(?i)encoding=['\"](\w+)['\"]", content) ##<?xml version='1.0' encoding='gb2312' ?>
    if m:
        encoding = m.group(1)
        xml_content = open(xmlConfigFile).read().decode(encoding).encode('UTF-8').replace(encoding, 'utf-8',1)
        dom = xml.dom.minidom.parseString(xml_content)
    else:
        dom = xml.dom.minidom.parse(xmlConfigFile)
##        
    root = dom.documentElement
    ##print "======Additional======"
    for i in root.getElementsByTagName('AdditionalField')[0].getElementsByTagName('Field'):
        fc.additionalField.append(getAdditionalField(i))
    ##print "=====Common======="
    fc.commonField = fc.additionalField
    fc.commonFieldOnly = []
    for i in root.getElementsByTagName('CommonField')[0].getElementsByTagName('Field'):
        fc.commonField.append(getField(i))
        fc.commonFieldOnly.append(getField(i))
    ##print "=====Type======="
    for i in root.getElementsByTagName('MessageType')[0].getElementsByTagName('Type'):
        tname = str(i.getAttribute('name'))
        tcondition = str(i.getAttribute('condition'))
        fc.dataType.append(tname)
        fc.conditionByType[tname] = tcondition
        fc.typedField[tname] = fc.commonField[:]
        fc.typedFieldOnly[tname] = []
        for j in i.getElementsByTagName('Field'):
            fc.typedField[tname].append(getField(j))
            fc.typedFieldOnly[tname].append(getField(j))
    return fc

class WTSCommand(object):
    def __init__(self, name, cmd_type, title, comment):
        self.name = name
        self.title = title
        self.comment = comment
        self.type = cmd_type
        self.fields = [] # [[u'Addr', 0, None, 'uint16', u'const', {'value': 65535}],...]
    
def makeCommandfromXML(xe):
    cmd_type = xe.getAttribute('type')
    cmd_name = xe.getAttribute('name')
    cmd_title = getDefault(xe.getAttribute('title'),cmd_name)
    cmd_comment = xe.getAttribute('comment')
    c = WTSCommand(cmd_name, cmd_type, cmd_title, cmd_comment)
    for i in xe.getElementsByTagName('Field'):  # <Field name=xxx>
        fieldName = i.getAttribute('name')
        fieldBegin = int(i.getAttribute('begin'),0)
        fieldEnd = int(i.getAttribute('end'),0) if i.hasAttribute('end') else None
        fieldType = i.getAttribute('type')
        value = i.getElementsByTagName('Value')[0] # <Value xxx=xxx>
        valueType = value.getAttribute('type')
        options = {}
        if valueType=="time_second":
            pass
        elif valueType=="time_ticks":
            pass
        elif valueType=="const":
            if value.hasAttribute("value"):
                options["value"] = int(value.getAttribute("value"),0)
            else:
                options["value"] = 0
        elif valueType=="random":
            if value.hasAttribute("min"):
                options["min"]=int(value.getAttribute("min"),0)
            else:
                options["min"]=0
            if value.hasAttribute("max"):
                options["max"]=int(value.getAttribute("max"),0)
            else:
                options["max"]=0
        elif valueType=="unique8":
            pass
        elif valueType=="unique16":
            pass
        elif valueType=="int":
            if value.hasAttribute("min"):
                options["min"]=int(value.getAttribute("min"),0)
            else:
                options["min"]=0
            if value.hasAttribute("max"):
                options["max"]=int(value.getAttribute("max"),0)
            else:
                options["max"]=0            
            if value.hasAttribute("default"):
                options["default"]=int(value.getAttribute("default"),0)
            else:
                options["default"] = options["min"]
            options["comment"] = value.getAttribute("comment")
        else:
            print "cmd_name=",cmd_name,"fieldName=", fieldName, "valueType=", valueType
            logging.critical("Critical Error in XML: cmd_name=%s fieldName=%s valueType=%s",cmd_name,fieldName,valueType)
            raise WTSException
        c.fields.append([fieldName,fieldBegin,fieldEnd,fieldType,valueType,options])
    return c
        
def ParseCommandXML(xmlConfigFile):
    fc = FieldConfig()
    content = open(xmlConfigFile).readline()
    m = re.search("(?i)encoding=['\"](\w+)['\"]", content) ##<?xml version='1.0' encoding='gb2312' ?>
    if m:
        encoding = m.group(1)
        xml_content = open(xmlConfigFile).read().decode(encoding).encode('UTF-8').replace(encoding, 'utf-8',1)
        dom = xml.dom.minidom.parseString(xml_content)
    else:
        dom = xml.dom.minidom.parse(xmlConfigFile)
##        
    root = dom.documentElement
    cmd_by_title = {}
    cmd_title_by_type = {}
    cmd_by_name = {}
    for i in  root.getElementsByTagName('Command'):
        c = makeCommandfromXML(i)
        cmd_title_by_type.setdefault(c.type,[]).append(c.title)
        # cmd_title_by_type:
        #       { "Control": ["control cmd1", "control cmd2","control cmd3"],
        #        "Debug": ["debug cmd1", "debug cmd2","debug cmd3"]
        #       }
        cmd_by_title[c.title]=c
        cmd_by_name[c.name]=c
    return cmd_title_by_type,cmd_by_title,cmd_by_name

    
if __name__ == "__main__":
  #  if 0:
        fc = ParsePacketXML("packet_define_zn0x.xml")
        print "========fc.additionalField=============="
        print fc.additionalField
        print "===========fc.commonFiled=============="
        print fc.commonField
        print "========fc.commonFieldOnly=============="        
        print fc.commonFieldOnly
        print "========fc.dataType=============="        
        print fc.dataType
        print "========fc.typedFieldOnly=============="        
        print fc.typedFieldOnly
        print "========fc.conditionByType=============="        
        print fc.conditionByType
      #if 1:
        # c1,c2 = ParseCommandXML("command_define_zn0x.xml")
       #  print c1
        # print c2
        # for i in c2:
          #   print c2[i].fields
